/*******************************************************************************
 * Copyright (c) 2009 IBM Corporation and others
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.aseclipse.osgi.loader
{
    import flash.events.Event;
    import flash.events.IEventDispatcher;
    
    import mx.events.ResourceEvent;
    import mx.logging.ILogger;
    import mx.logging.Log;
    import mx.resources.IResourceBundle;
    import mx.resources.IResourceManager;
    import mx.resources.ResourceBundle;
    import mx.resources.ResourceManager;
        
    public class BundleLocaleLoader
    {
        private static var resourceManager:IResourceManager = ResourceManager.getInstance();
        private static var firstTime:Boolean = true;
        private static var log_:ILogger = Log.getLogger("BundleThemeLoader");
        private var oldLocale:String = "en_US";
        private var localeUrl:String = null;
        
        public static var preloadResources:Array = new Array();
        
        public function BundleLocaleLoader()
        {
        }
        
        public static function getInstance():BundleLocaleLoader {
            return new BundleLocaleLoader();
        }
                
        public static function getURL(bundle:String, locale:String):String {
            var url:String = BundleConstants.getURLPrefix() + bundle  + "_" +locale + ".swf"; // OSGiConstants.URL_PREFIX + 
            url = BundleConstants.updateSubfix(url);
            return url; 
        }
        
        private var array:Array;
        
        public function loadResources(bundles:*, callbacks:Function, locale:String = "en_US"):void {
            if(firstTime == true) {
                recordDefaultBundles(locale);
                firstTime = false;
            }
            if(bundles == null) 
                return;
            if(bundles is String) {
                if(alreadyLoaded(bundles, locale)) {
                    if(callbacks != null) {
                        callbacks.apply(null);
                        callbacks = null;
                    }
                    return;
                }
                var url:String = getURL(bundles as String, locale);
                log_.info("load resource: " + url);
                localeUrl = url;
                var eventDispatcher:IEventDispatcher = resourceManager.loadResourceModule(url, false);
                var f1:Function = function(event1:Event):void {
                    log_.debug("--->> Success loading resource: " + url);
                    eventDispatcher.removeEventListener(ResourceEvent.COMPLETE, f1);
                    if(callbacks != null) {
                        callbacks.apply(null);
                        callbacks = null;
                    }
                    resourceManager.update();
                };
                var f2:Function = function(event2:Event):void {
                    log_.debug("--->> Fail loading resource: " + url);
                    eventDispatcher.removeEventListener(ResourceEvent.ERROR, f2);
                    eventDispatcher.addEventListener(ResourceEvent.ERROR, f3);
                    if(callbacks != null) {
                        callbacks.apply(null);
                        callbacks = null;
                    }
                };
                var f3:Function = function(event3:Event):void {
                    log_.debug("--->> Fail loading resource: " + event3.toString());
                }
                eventDispatcher.addEventListener(ResourceEvent.COMPLETE, f1);
                eventDispatcher.addEventListener(ResourceEvent.ERROR, f2);    
                eventDispatcher.addEventListener(ResourceEvent.PROGRESS, progressHander);                
            } else if(bundles is Array) {
                array = bundles as Array;
                startLoad(locale, callbacks);
            }
        }

        private function progressHander(event:ResourceEvent):void {
        }
                
        protected function startLoad(locale:String, callbacks:Function):void {
            try {
                var key:String = array.pop() as String;
                if(key != null) {
                	if(alreadyLoaded(key, locale)) {
                		startLoad(locale, callbacks);
                		return;
                	}
                	
                    var url:String = getURL(key, locale);
                    log_.info("load resource: " + url);
                    localeUrl = url;
                    var eventDispatcher:IEventDispatcher = resourceManager.loadResourceModule(url, false);
                    var f1:Function = function(event1:Event):void {
                        log_.debug("--->> Success loading resource: " + url);
                        eventDispatcher.removeEventListener(ResourceEvent.COMPLETE, f1);
                        startLoad(locale, callbacks);     
                    };
                    var f2:Function = function(event2:Event):void {
                        log_.debug("--->> Fail loading resource: " + url);
                        eventDispatcher.removeEventListener(ResourceEvent.ERROR, f2);
                        eventDispatcher.addEventListener(ResourceEvent.ERROR, f3);
                        startLoad(locale, callbacks);
                    };
                    var f3:Function = function(event3:Event):void {
                    	log_.debug("--->> Fail loading resource: " + event3.toString());
                    }
                    eventDispatcher.addEventListener(ResourceEvent.COMPLETE, f1);
                    eventDispatcher.addEventListener(ResourceEvent.ERROR, f2);
                    eventDispatcher.addEventListener(ResourceEvent.PROGRESS, progressHander);
                } else {
                    if(callbacks != null) {
                        callbacks.apply(null);               
                        callbacks = null;
                    }
                    resourceManager.update();
                }
            } catch(err:Error) {
                log_.warn(err.getStackTrace());
            }
        }
        
        private static var defaultBundles:Array = new Array();
        private static function recordDefaultBundles(locale:String):void {
            defaultBundles = resourceManager.getBundleNamesForLocale(locale);
            logLocale("Default Locale", defaultBundles);
        }
        
        private static function logLocale(title:String, bun:Array):void {
            if(Log.isDebug()) {
                var log:String = "";
                for each(var key:String in bun) {
                    log = log + ", " + key;
                }
                log_.debug(title+ ": " + log);
            }                
        }
        
        private static function getCustomBundles(locale:String):Array {
            var bundles:Array = resourceManager.getBundleNamesForLocale(locale);
            var customBundles:Array = new Array();
            for each(var newKey:String in bundles) {
                if(defaultBundles.indexOf(newKey)<0 && preloadResources.indexOf(newKey)<0) {
                    customBundles.push(newKey);
                }
            }
            customBundles = customBundles.concat(preloadResources);
            return customBundles;
        }
        
        public function changeLocale(oldLocale:String, newLocale:String):void {
            var bundles:Array = getCustomBundles(oldLocale);
            this.oldLocale = oldLocale;
            logLocale("Custom Locale", bundles);
            var changeChain:Function = function():void {
                if(newLocale=="en_US") {
                	resourceManager.localeChain = [ "en_US" ];
                }else {
	                resourceManager.localeChain = [ newLocale, "en_US" ];
                }
                log_.info("Change language: " + newLocale);
            }
            loadResources(bundles, changeChain, newLocale);
        }
                
        private function alreadyLoaded(bundle:String, locale:String):Boolean {
            return resourceManager.getResourceBundle(locale, bundle)!=null;
        }
        
        /*
         * Copy a bundle resource from one locale to another locale
         */
        private function copyBundle(bundle:String, fromLocale:String, toLocale:String):void {
        	if(fromLocale==toLocale) return;
        	var tmpRb1:IResourceBundle = resourceManager.getResourceBundle(fromLocale, bundle);
        	var tmpRb2:ResourceBundle = new ResourceBundle(toLocale, bundle);
        	if(tmpRb1!=null) {
        		var tmp1Content:Object = tmpRb1.content ;
        		var tmp2Content:Object = tmpRb2.content ;
        		for(var tmpName:Object in tmp1Content) {
        			tmp2Content[tmpName] = tmp1Content[tmpName] ;
        		}
        	}
        	resourceManager.addResourceBundle(tmpRb2);
        }
    }
}
